// IA32NestedLoopDetector.h

#ifndef IA32NESTEDLOOPDETECTOR_H
#define IA32NESTEDLOOPDETECTOR_H

#include <iostream>
#include <vector>
#include "crossbit/NestedLoopDetector.h"

namespace crossbit
{
	class IA32NestedLoopDetector : public NestedLoopDetector
	{
		typedef struct struct_loop_info
		{
			XTMemAddr entry;
			XTMemAddr exit;
			RegNum bound_reg;
			XTInt32 bound_off;

			struct_loop_info()
				: entry(0), exit(0), bound_reg(0), bound_off(0)
			{}

			struct_loop_info(XTMemAddr e, XTMemAddr x, RegNum r, XTInt32 o)
				: entry(e), exit(x), bound_reg(r), bound_off(o)
			{}
		}LOOP_INFO;

		typedef struct struct_loop_basic
		{
			XTMemAddr entry;
			XTMemAddr exit;
			struct_loop_basic()
				: entry(0), exit(0) {}
			struct_loop_basic(XTMemAddr a, XTMemAddr b)
				: entry(a), exit(b) {}
		}LOOP_BASIC;

		typedef struct struct_nested_loop
		{
			LOOP_INFO outmost;
			std::vector<LOOP_INFO> inners;
		}NESTED_LOOP;

		public:
			IA32NestedLoopDetector( Interpreter *i )
				: NestedLoopDetector( i )
			{
				nested_count = 0;
				last_entry = 0;
				last_exit = 0;
			}
			IA32NestedLoopDetector(XTMemAddr a, XTMemAddr b, Interpreter *i)
				: NestedLoopDetector(a, b, i)
			{
				nested_count = 0;
				last_entry = a;
				last_exit = b;
			}

			~IA32NestedLoopDetector()
			{}

			void run();

			XTMemAddr decode(XTMemAddr at);

			XTInt32 isNestedLoop(XTMemAddr entry);

			void printNestedLoops();

			XTMemAddr getOutmostEntry();
			XTMemAddr getOutmostExit();

			virtual void setTextSectionRange( XTMemAddr s, XTMemAddr e )
			{
				start = s;
				end = e;
				last_entry = s;
				last_exit = e;
			}

		private:
			bool __getBoundInfo(XTMemAddr entry, RegNum &reg, XTInt32 &off);
		private:
			std::vector<LOOP_BASIC> cur_nest;	// record current nested loops for furthur analysis
			std::vector<NESTED_LOOP> nested_loops;

			XTInt32 nested_count;
			XTMemAddr last_entry;
			XTMemAddr last_exit;

		public:
			// decode functions for x86 jmp instructions
        	void i_jmp_nest(x86_insn *insn, x86_operand *op, XTMemAddr cur);
	};

	typedef void (IA32NestedLoopDetector::*NestDecodePtr_t)(x86_insn *insn, x86_operand *op, XTMemAddr cur);
}

#endif
